<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=682299
-->
<head>
  <title>Test for Bug 682299</title>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <script type="application/javascript" src="/tests/dom/media/test/manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=682299">Mozilla Bug 682299</a>
<p id="display"></p>
<div id="content" style="display: none">
  
</div>
<pre id="test">
<script type="application/javascript">

/** Test for Bug 682299 **/
SimpleTest.requestFlakyTimeout("untriaged");

function createCanvas(width, height) {
  var c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  return c;
}

function checkGetImageData(ctx, v) {
  try {
    var data = ctx.getImageData(0, 0, 1, 1);
    ok(true, "drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' worked");
  } catch(error) {
    ok(!v.crossOrigin && error.name === "SecurityError", "drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' failed");
    v.tainted = true;
  }
}

function checkGetImageDataTainted(ctx, v) {
  try {
    var data = ctx.getImageData(0, 0, 1, 1);
    ok(false, "changing the CORS mode should not allow reading data from remote videos");
  } catch (error) {
    ok(error.name === "SecurityError", "changing the CORS mode, drawImage '" + v.src + "' then getImageData with crossOrigin='" + v.crossOrigin + "' failed");
  }
}

function checkCaptureStream(c, v) {
  try {
    var stream = c.captureStream(0);
    ok(true, "drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' worked");
  } catch(error) {
    ok(!v.crossOrigin && error.name === "SecurityError", "drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' failed");
    v.tainted = true;
  }
}

function checkCaptureStreamTainted(c, v) {
  try {
    var stream = c.captureStream(0);
    ok(false, "changing the CORS mode should not allow capturing a stream from remote videos");
  } catch (error) {
    ok(error.name === "SecurityError", "changing the CORS mode, drawImage '" + v.src + "' then captureStream with crossOrigin='" + v.crossOrigin + "' failed");
  }
}

function testCanvasDrawImage(v) {
  var c = createCanvas(v.width, v.height);
  var ctx = c.getContext("2d");
  ctx.drawImage(v, 0, 0);

  checkGetImageData(ctx, v);
  checkCaptureStream(c, v);
}

function testCanvasCreatePattern(v) {
  var c = createCanvas(v.width, v.height);
  var ctx = c.getContext("2d");
  ctx.fillStyle = ctx.createPattern(v, "");
  ctx.fillRect(0, 0, c.width, c.height);

  checkGetImageData(ctx, v);
  checkCaptureStream(c, v);
}

function testWebGL(gl, v) {
  var tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);

  try {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, v);
    ok(true, "createTexture from '" + v.src + "' with crossOrigin='" + v.crossOrigin + "' worked");
  } catch (error) {
    ok(!v.crossOrigin && error.name === "SecurityError", "createTexture from '" + v.src + "' with crossOrigin='" + v.crossOrigin + "' failed");
    v.tainted = true;
  }
}

function testTaintedCanvas(v) {
  var c = createCanvas(v.width, v.height);
  var ctx = c.getContext("2d");
  ctx.drawImage(v, 0, 0);

  checkGetImageDataTainted(ctx, v);
  checkCaptureStreamTainted(c, v);
}

function vidDataSuccess(e) {
  ok(!e.target.error, "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'");

  testCanvasDrawImage(e.target);
  testCanvasCreatePattern(e.target);
  if (document.gl) {
    testWebGL(document.gl, e.target);
  }
  // If we change the CORS mode after loading the file without CORS it should still throw a security error
  if (e.target.tainted) {
    e.target.crossOrigin = "anonymous";
    testTaintedCanvas(e.target);
  }

  doneTest(e);
}

function vidLoadFailure(e) {
  ok(false, "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'");
  doneTest(e);
}

function vidErrorSuccess(e) {
  ok(e.target.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, 
    "Load '" + e.target.src + "' with crossOrigin='" + e.target.crossOrigin + "'");
  doneTest(e);
}

function startTest(test, token) {
  var v = document.createElement('video');
  if (test.cors === "just-crossOrigin-without-value") {
    var div = document.createElement('div');
    div.innerHTML="<video crossOrigin>";
    v = div.children[0];
  } else if (test.cors !== "missing-value-default") {
    v.crossOrigin = test.cors;
  }
  v.token = token;
  document.manager.started(token);
  v.autoplay = true;
  v.preload = "auto";
  v.style.display = "none";
  if (test.nameIntent === test.corsIntent || test.corsIntent === "none" ||
      (test.nameIntent === "use-credentials" && test.corsIntent === "anonymous")) {
    v.addEventListener("loadeddata", vidDataSuccess, false);
    v.addEventListener("error", vidLoadFailure, false);
  } else {
    v.addEventListener("loadeddata", vidLoadFailure, false);
    v.addEventListener("error", vidErrorSuccess, false);
  }
  v.src = test.name;
  document.body.appendChild(v);
}

function doneTest(e) {
  var v = e.target;
  v.parentNode.removeChild(v);
  document.manager.finished(v.token);
}

function beginTest() {
  var videoFile = getPlayableVideo(gSmallTests);
  if (!videoFile) {
    SimpleTest.finish();
  }
  videoFile = "?name=tests/dom/media/test/" + videoFile.name + "&type=" + videoFile.type;

  document.manager = new MediaTestManager;
  var corsTests = [];

  const host = "http://example.com/tests/dom/canvas/test/crossorigin/video.sjs";
  const serverAttrValues = [
    [ "&cors=none", "none" ],
    [ "&cors=anonymous", "anonymous" ],
    [ "&cors=use-credentials", "use-credentials" ]
  ];
  const clientAttrValues = [
    [ "missing-value-default", "none" ],
    [ "", "anonymous" ],
    [ "just-crossOrigin-without-value", "anonymous" ],
    [ "anonymous", "anonymous" ],
    [ "use-credentials", "use-credentials" ],
    [ "foobar", "anonymous" ]
  ];

  // Build the video file test array
  for (var i = 0; i < serverAttrValues.length; i++) {
    for (var n = 0; n < clientAttrValues.length; n++) {
      corsTests.push({
        name: host + videoFile + serverAttrValues[i][0],
        nameIntent: serverAttrValues[i][1],
        cors: clientAttrValues[n][0],
        corsIntent: clientAttrValues[n][1]
      });
    }
  }
  try {
    document.gl = createCanvas(16, 16).getContext("experimental-webgl");
  } catch (ex) {
    // Mac OS X 10.5 doesn't support WebGL, so we won't run the WebGL tests
  }
  document.manager.runTests(corsTests, startTest);
}

SimpleTest.waitForExplicitFinish();
beginTest();
</script>
</pre>
</body>
</html>
